"""
新闻分析工具模块

提供新闻情感分析、关键词提取、重要性评分等功能
"""

import re
import jieba
from typing import List, Dict, Any, Optional, Tuple
import logging
from datetime import datetime, timedelta
from ..models.market_data import NewsItem
from ..models.analysis_results import SentimentAnalysis
import time
logger = logging.getLogger(__name__)


class NewsAnalyzer:
    """新闻分析工具类"""
    
    def __init__(self):
        """初始化新闻分析工具"""
        # 导入专业A股关键词（与专业分析保持一致）
        try:
            from ..config.sentiment_prompts import SentimentPrompts
            a_share_keywords = SentimentPrompts.get_a_share_specific_keywords()

            # 基于专业A股关键词构建情感词典
            self.positive_words = set()
            self.negative_words = set()

            # 从专业关键词中提取正面词汇
            if "政策利好" in a_share_keywords:
                self.positive_words.update(a_share_keywords["政策利好"])
            if "业绩表现" in a_share_keywords:
                # 业绩相关的正面词汇
                performance_words = [word for word in a_share_keywords["业绩表现"]
                                   if any(pos in word for pos in ['增长', '上升', '提升', '改善', '扭亏为盈'])]
                self.positive_words.update(performance_words)

            # 从专业关键词中提取负面词汇
            if "监管风险" in a_share_keywords:
                self.negative_words.update(a_share_keywords["监管风险"])

            # 补充传统情感词汇（保持兼容性）
            traditional_positive = {
                '上涨', '涨幅', '增长', '利好', '突破', '创新高', '盈利', '收益',
                '增收', '扩张', '合作', '签约', '中标', '获得', '成功',
                '优秀', '强劲', '稳定', '改善', '提升', '超预期', '看好', '推荐',
                '买入', '增持', '目标价', '上调', '乐观', '积极', '正面'
            }

            traditional_negative = {
                '下跌', '跌幅', '下降', '利空', '跌破', '创新低', '亏损', '损失',
                '减收', '收缩', '分歧', '取消', '失败', '风险', '担忧',
                '疲软', '恶化', '下滑', '低于预期', '看空', '减持', '卖出',
                '下调', '悲观', '消极', '负面', '警告', '暂停', '延期'
            }

            self.positive_words.update(traditional_positive)
            self.negative_words.update(traditional_negative)

        except ImportError:
            # 如果无法导入专业配置，使用传统词典
            logger.warning("无法导入专业A股关键词，使用传统情感词典")
            self.positive_words = {
                '上涨', '涨幅', '增长', '利好', '突破', '创新高', '盈利', '收益',
                '业绩', '增收', '扩张', '合作', '签约', '中标', '获得', '成功',
                '优秀', '强劲', '稳定', '改善', '提升', '超预期', '看好', '推荐',
                '买入', '增持', '目标价', '上调', '乐观', '积极', '正面'
            }

            self.negative_words = {
                '下跌', '跌幅', '下降', '利空', '跌破', '创新低', '亏损', '损失',
                '业绩', '减收', '收缩', '分歧', '取消', '失败', '风险', '担忧',
                '疲软', '恶化', '下滑', '低于预期', '看空', '减持', '卖出',
                '下调', '悲观', '消极', '负面', '警告', '暂停', '延期'
            }

        # 重要性关键词（增强A股特色）
        self.importance_keywords = {
            # 传统重要性词汇
            '重大': 3.0, '重要': 2.5, '关键': 2.0, '核心': 2.0, '主要': 1.5,
            '首次': 2.0, '突破': 2.5, '创新': 2.0, '战略': 2.5,

            # A股特色重要性词汇
            '合并': 3.0, '收购': 2.5, '重组': 2.5, '上市': 3.0, '退市': 3.0,
            '停牌': 2.0, '复牌': 2.0, '分红': 1.5, '配股': 2.0, '增发': 2.0,
            '回购': 2.0, '定增': 2.0, '股权激励': 2.5, '业绩预告': 2.0,

            # 监管相关
            '监管': 2.5, '处罚': 3.0, '立案': 3.0, '调查': 2.5, '违规': 2.5,
            'ST': 3.0, '*ST': 3.5, '退市风险': 3.5,

            # 政策相关
            '政策': 2.0, '国家': 2.5, '央行': 2.5, '证监会': 2.5, '银保监会': 2.5
        }

        logger.info(f"新闻分析工具初始化完成 - 正面词汇{len(self.positive_words)}个，负面词汇{len(self.negative_words)}个，重要性词汇{len(self.importance_keywords)}个")
    
    def calculate_sentiment_score(self, text: str, mode: str = "basic") -> float:
        """
        计算文本情感分数（基础词典分析，用于快速筛选和预处理）

        Args:
            text: 文本内容
            mode: 分析模式 ("basic" - 基础分析, "enhanced" - 增强分析)

        Returns:
            float: 情感分数 (-1到1之间)

        Note:
            这是基础的词典分析，主要用于：
            1. 快速预筛选新闻
            2. 为专业LLM分析提供参考
            3. 在LLM不可用时提供备用分析
        """
        if not text:
            return 0.0

        # 分词
        words = list(jieba.cut(text))

        positive_count = 0
        negative_count = 0
        total_words = len(words)

        # A股特色：增加权重词汇识别
        high_weight_positive = {'利好', '超预期', '突破', '创新高', '重大合作'}
        high_weight_negative = {'利空', '跌破', '创新低', '重大风险', '监管处罚'}

        for word in words:
            if word in self.positive_words:
                # A股特色词汇给予更高权重
                weight = 2.0 if word in high_weight_positive else 1.0
                positive_count += weight
            elif word in self.negative_words:
                # A股特色词汇给予更高权重
                weight = 2.0 if word in high_weight_negative else 1.0
                negative_count += weight

        total_sentiment_words = positive_count + negative_count
        if total_sentiment_words == 0:
            return 0.0

        # 计算基础情感分数
        sentiment_score = (positive_count - negative_count) / total_sentiment_words

        # 增强模式：考虑文本长度和情感词密度
        if mode == "enhanced":
            sentiment_density = total_sentiment_words / max(total_words, 1)
            # 情感词密度越高，置信度越高
            confidence_factor = min(sentiment_density * 2, 1.0)
            sentiment_score *= confidence_factor

        return max(-1.0, min(1.0, sentiment_score))
    
    def calculate_importance_score(self, title: str, content: str = "") -> float:
        """
        计算新闻重要性分数
        
        Args:
            title: 新闻标题
            content: 新闻内容
            
        Returns:
            float: 重要性分数 (0到1之间)
        """
        text = title + " " + content
        words = list(jieba.cut(text))
        
        importance_score = 0.0
        for word in words:
            if word in self.importance_keywords:
                importance_score += self.importance_keywords[word]
        
        # 标准化到0-1之间
        max_possible_score = 10.0  # 假设的最大可能分数
        normalized_score = min(1.0, importance_score / max_possible_score)
        
        return normalized_score
    
    def extract_key_themes(self, news_list: List[NewsItem]) -> List[str]:
        """
        提取关键主题
        
        Args:
            news_list: 新闻列表
            
        Returns:
            List[str]: 关键主题列表
        """
        if not news_list:
            return []
        
        # 合并所有新闻文本
        all_text = ""
        for news in news_list:
            all_text += news.title + " " + (news.content or "")
        
        # 分词并统计词频
        words = list(jieba.cut(all_text))
        word_freq = {}
        
        for word in words:
            if len(word) > 1 and word not in ['的', '是', '在', '有', '和', '与', '及', '等']:
                word_freq[word] = word_freq.get(word, 0) + 1
        
        # 按频率排序，取前10个
        sorted_words = sorted(word_freq.items(), key=lambda x: x[1], reverse=True)
        themes = [word for word, freq in sorted_words[:10] if freq > 1]
        
        return themes
    
    def analyze_news_sentiment(self, news_list: List[NewsItem], analysis_mode: str = "basic") -> SentimentAnalysis:
        """
        分析新闻情感（基础分析，为专业LLM分析提供预处理）

        Args:
            news_list: 新闻列表
            analysis_mode: 分析模式 ("basic" - 基础分析, "enhanced" - 增强分析)

        Returns:
            SentimentAnalysis: 基础情感分析结果

        Note:
            这是基础的情感分析，主要作用：
            1. 快速预处理和筛选新闻
            2. 为专业A股LLM分析提供基础数据
            3. 在专业分析不可用时提供备用结果
            4. 计算重要性分数和关键主题
        """
        if not news_list:
            return SentimentAnalysis(
                signal="neutral",
                confidence=0.0,
                reasoning="无新闻数据",
                sentiment_score=0.0,
                news_count=0
            )
        
        try:
            sentiment_scores = []
            positive_count = 0
            
            # 计算每条新闻的情感分数和重要性
            for news in news_list:
                text = news.title + " " + (news.content or "")
                # 使用指定的分析模式
                sentiment = self.calculate_sentiment_score(text, mode=analysis_mode)
                importance = self.calculate_importance_score(news.title, news.content or "")

                # 根据重要性加权情感分数
                weighted_sentiment = sentiment * (1 + importance)
                sentiment_scores.append(weighted_sentiment)

                if sentiment > 0:
                    positive_count += 1

                # 更新新闻项的情感分数和重要性
                news.sentiment_score = sentiment
                news.importance = importance
            
            # 计算总体情感分数
            if sentiment_scores:
                overall_sentiment = sum(sentiment_scores) / len(sentiment_scores)
            else:
                overall_sentiment = 0.0
            
            # 计算正面新闻比例
            positive_ratio = positive_count / len(news_list) if news_list else 0.0
            
            # 提取关键主题
            key_themes = self.extract_key_themes(news_list)
            
            # 判断情感信号（基础分析）
            if overall_sentiment > 0.3:
                signal = "bullish"
                confidence = min(abs(overall_sentiment), 1.0)
                reasoning = f"基础词典分析：新闻整体偏正面，情感分数{overall_sentiment:.2f}（建议结合专业A股分析）"
            elif overall_sentiment < -0.3:
                signal = "bearish"
                confidence = min(abs(overall_sentiment), 1.0)
                reasoning = f"基础词典分析：新闻整体偏负面，情感分数{overall_sentiment:.2f}（建议结合专业A股分析）"
            else:
                signal = "neutral"
                confidence = 1.0 - abs(overall_sentiment)
                reasoning = f"基础词典分析：新闻情感中性，情感分数{overall_sentiment:.2f}（建议结合专业A股分析）"
            
            # 生成市场情绪描述
            if positive_ratio > 0.7:
                market_mood = "市场情绪乐观"
            elif positive_ratio < 0.3:
                market_mood = "市场情绪悲观"
            else:
                market_mood = "市场情绪中性"
            
            return SentimentAnalysis(
                signal=signal,
                confidence=confidence,
                reasoning=reasoning,
                sentiment_score=overall_sentiment,
                news_count=len(news_list),
                positive_news_ratio=positive_ratio,
                key_themes=key_themes,
                market_mood=market_mood
            )
            
        except Exception as e:
            logger.error(f"新闻情感分析失败: {e}")
            return SentimentAnalysis(
                signal="neutral",
                confidence=0.0,
                reasoning=f"分析失败: {str(e)}",
                sentiment_score=0.0,
                news_count=len(news_list)
            )
    
    def filter_relevant_news(
        self, 
        news_list: List[NewsItem], 
        ticker: str,
        days_back: int = 7
    ) -> List[NewsItem]:
        """
        过滤相关新闻
        
        Args:
            news_list: 新闻列表
            ticker: 股票代码
            days_back: 回溯天数
            
        Returns:
            List[NewsItem]: 过滤后的新闻列表
        """
        if not news_list:
            return []
        
        cutoff_date = datetime.now() - timedelta(days=days_back)
        relevant_news = []
        
        for news in news_list:
            # 时间过滤
            if news.publish_time < cutoff_date:
                continue
            
            # 相关性过滤（简单的关键词匹配）
            text = news.title + " " + (news.content or "")
            if ticker in text or any(keyword in text for keyword in [
                '股票', '股价', '投资', '交易', '市场', '行业', '公司', '业绩'
            ]):
                relevant_news.append(news)
        
        # 按时间排序，最新的在前
        relevant_news.sort(key=lambda x: x.publish_time, reverse=True)
        
        logger.info(f"过滤得到相关新闻 {len(relevant_news)} 条")
        return relevant_news
    
    def generate_news_summary(self, news_list: List[NewsItem]) -> str:
        """
        生成新闻摘要
        
        Args:
            news_list: 新闻列表
            
        Returns:
            str: 新闻摘要
        """
        if not news_list:
            return "无相关新闻"
        
        # 按重要性排序
        sorted_news = sorted(news_list, key=lambda x: x.importance or 0, reverse=True)
        
        summary_parts = []
        for i, news in enumerate(sorted_news[:5]):  # 取前5条重要新闻
            summary_parts.append(f"{i+1}. {news.title}")
        
        summary = "重要新闻摘要:\n" + "\n".join(summary_parts)
        
        # 添加情感统计
        positive_count = sum(1 for news in news_list if (news.sentiment_score or 0) > 0)
        negative_count = sum(1 for news in news_list if (news.sentiment_score or 0) < 0)
        
        summary += f"\n\n情感统计: 正面{positive_count}条, 负面{negative_count}条, 总计{len(news_list)}条"
        
        return summary

    def prepare_for_professional_analysis(self, news_list: List[NewsItem]) -> Dict[str, Any]:
        """
        为专业A股分析准备数据

        Args:
            news_list: 新闻列表

        Returns:
            Dict[str, Any]: 预处理后的数据，供专业LLM分析使用
        """
        if not news_list:
            return {
                "news_data": [],
                "basic_sentiment": 0.0,
                "importance_ranking": [],
                "key_themes": [],
                "summary": "无新闻数据"
            }

        # 进行基础分析
        basic_analysis = self.analyze_news_sentiment(news_list, analysis_mode="enhanced")

        # 按重要性排序新闻
        news_with_scores = []
        for news in news_list:
            text = news.title + " " + (news.content or "")
            sentiment = self.calculate_sentiment_score(text, mode="enhanced")
            importance = self.calculate_importance_score(news.title, news.content or "")

            news_with_scores.append({
                "news": news,
                "sentiment": sentiment,
                "importance": importance,
                "combined_score": abs(sentiment) * (1 + importance)  # 重要性和情感强度的组合
            })

        # 按综合分数排序
        news_with_scores.sort(key=lambda x: x["combined_score"], reverse=True)

        # 准备给LLM的数据
        prepared_data = {
            "news_data": [
                {
                    "title": item["news"].title,
                    "content": item["news"].content or "",
                    "publish_time": item["news"].publish_time.isoformat() if item["news"].publish_time else "",
                    "source": getattr(item["news"], "source", ""),
                    "basic_sentiment": item["sentiment"],
                    "importance": item["importance"]
                }
                for item in news_with_scores[:10]  # 取前10条最重要的新闻
            ],
            "basic_sentiment": basic_analysis.sentiment_score,
            "basic_signal": basic_analysis.signal,
            "positive_ratio": basic_analysis.positive_news_ratio,
            "key_themes": basic_analysis.key_themes,
            "market_mood": basic_analysis.market_mood,
            "news_count": len(news_list),
            "summary": self.generate_news_summary(news_list)
        }

        return prepared_data

    def get_analysis_mode_recommendation(self, news_count: int, avg_importance: float) -> str:
        """
        根据新闻数量和重要性推荐分析模式

        Args:
            news_count: 新闻数量
            avg_importance: 平均重要性

        Returns:
            str: 推荐的分析模式
        """
        if news_count >= 10 and avg_importance > 0.5:
            return "detailed"  # 新闻多且重要性高，使用详细分析
        elif news_count >= 5:
            return "standard"  # 中等数量新闻，使用标准分析
        else:
            return "quick"     # 新闻较少，使用快速分析
